using JetBrains.Annotations;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Drivers;
using Orchard.Localization;
using Orchard.UI.Notify;
using Mod.NextPreviousItem.Models;
using Orchard;
using Mod.NextPreviousItem.Services;
using Mod.NextPreviousItem.Settings;
using Contrib.Taxonomies.Services;
using Orchard.Core.Common.Models;
using System;
using System.Linq;
using System.Collections.Generic;

namespace Mod.NextPreviousItems.Drivers
{
    [UsedImplicitly]
	
    public class NextPreviousItemPartDriver : ContentPartDriver<NextPreviousItemPart>
    {
        private readonly INotifier _notifier;
        private const string TemplateName = "Parts/NextPreviousItemPart";
        private readonly IOrchardServices services;
        private readonly IExtraTaxoService taxoService;
        private readonly ITaxonomyService taxonomyService;
        private readonly IContentManager manager;

        public Localizer T { get; set; }

        public NextPreviousItemPartDriver(INotifier notifier, IOrchardServices services, IExtraTaxoService taxoService,
            ITaxonomyService taxonomyService, IContentManager manager)
        {
            this.services = services;
            this.taxoService = taxoService;
            this.manager = manager;
            this.taxonomyService = taxonomyService;
            _notifier = notifier;
            T = NullLocalizer.Instance;
        }

        protected override DriverResult Display(NextPreviousItemPart part, string displayType, dynamic shapeHelper)
        {
            var common = part.ContentItem.As<CommonPart>();
            var settings = part.Settings.GetModel<NextPreviousTypePartSettings>();
            var pub = settings.Pub;
            var wrap = settings.Wrap;
            var terms = taxonomyService.GetTermsForContentItem(part.ContentItem.Id, settings.Taxonomy);
            var items = taxonomyService.GetContentItems(terms.First());

            return ContentShape("Parts_NextPreviousItemPart",
                () => {
                    var next = Next(part, items, common, pub, wrap);
                    var previous = Previous(part, items, common, pub, wrap);
                    var lame = wrap;
                    return shapeHelper.Parts_NextPreviousItemPart(PreviousItem: previous, NextItem: next);
                });
        }

        private ContentItem Previous(NextPreviousItemPart part, IEnumerable<IContent> items, CommonPart common, bool pub, bool wrap)
        {
            IContent item = null;

            if (pub)
            {
                item = items.Where(x => x.As<CommonPart>().PublishedUtc < common.PublishedUtc)
                    .OrderByDescending(x => x.As<CommonPart>().PublishedUtc)
                    .FirstOrDefault();
            }
            else
            {

                item = items.Where(x => x.As<CommonPart>().CreatedUtc < common.CreatedUtc)
                    .OrderByDescending(x => x.As<CommonPart>().CreatedUtc)
                    .FirstOrDefault();
            }

            if (item == null && wrap == true)
            {
                if (pub)
                    item = items.OrderBy(x => x.As<CommonPart>().PublishedUtc).FirstOrDefault();
                else
                    item = items.OrderBy(x => x.As<CommonPart>().CreatedUtc).FirstOrDefault();
            }
            return item == null ? null : item.ContentItem;
        }

        private ContentItem Next(NextPreviousItemPart part, IEnumerable<IContent> items, CommonPart common, bool pub, bool wrap)
        {
            IContent item = null;

            if (pub)
            {
                item = items.Where(x => x.As<CommonPart>().PublishedUtc > common.PublishedUtc)
                    .OrderBy(x => x.As<CommonPart>().PublishedUtc)
                    .FirstOrDefault();
            }
            else
            {
                item = items.Where(x => x.As<CommonPart>().CreatedUtc > common.CreatedUtc)
                    .OrderBy(x => x.As<CommonPart>().CreatedUtc)
                    .FirstOrDefault();
            }

            if (item == null && wrap == true)
            {
                if (pub)
                    item = items.OrderByDescending(x => x.As<CommonPart>().PublishedUtc).FirstOrDefault();
                else
                    item = items.OrderByDescending(x => x.As<CommonPart>().CreatedUtc).FirstOrDefault();
            }
            return item == null ? null : item.ContentItem;
        }
    }
}